AWS SAM CLI で Terraform で定義されたテンプレートと Lambda 関数のビルドとローカル実行がプレビュー機能としてサポートされました
いわさです。
AWS SAM CLI を使うと SAM で定義されたサーバーレスアプリケーションをローカル実行することが出来ます。
これまでは SAM テンプレートで定義されたものを実行する必要があったのですが、今回プレビュー機能として Terraform で定義されたサーバーレスアプリケーションもサポートされました。
何が出来るのか
具体的には、SAM CLI のコマンドのうち以下に関して--hook-name
オプションが追加され、Terraform であることを指定することが出来るようになりました。
これによって template.yml などを前提としていた各コマンドが main.tf でも実行出来ます。
- sam build
- sam local invoke
- sam local start-lambda
なお、サポートされているのはビルドとローカル実行のみなので、Terraform をsam deploy
出来るというわけではありません。
もしサーバーレスアプリケーションで DynamoDB などを実行してそれらを利用する場合は引き続きterraform apply
が必要です。
サンプルアプリケーション構造の確認
本日のアップデートにあわせてサンプルリポジトリが公開されていますのでこちらを使ってみます。
また、以下の AWS ブログでも上記リポジトリが利用されています。
このリポジトリには 2 つのサーバーレスアプリケーションが作成されていて、以下のブログでは API Gateway + Lambda + DynamoDB のapi-lambda-dynamodb-example
が使われていますが、私は本日はよりシンプルなlambda-example
を使ってみました。
サンプル Lambda 関数が固定のレスポンスをするだけの非常にシンプルなものです。
以下の記事では関連リソースとして事前にterraform apply
していますが、こちらの場合は単独でローカルコンテナで実行するだけなので不要です。
サンプルアプリケーションのコードをポイントを抜粋して取り上げます。
Lambda 関数は以下のみです。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 import json def lambda_handler(event, context): event_body = json.loads(event['body']) print(event_body) return { 'statusCode': 200, 'body': "Request Received!", 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }
続いて main.tf です。
template.yml は存在せず、main.tf でハンドラーが定義されています。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 terraform { : resource "aws_lambda_function" "hello-terraform" { filename = "${local.building_path}/${local.lambda_code_filename}" handler = "index.lambda_handler" runtime = "python3.8" function_name = "hello-terraform" role = aws_iam_role.iam_for_lambda.arn timeout = 30 depends_on = [ null_resource.build_lambda_function ] } resource "null_resource" "sam_metadata_aws_lambda_function_hello_terraform" { triggers = { resource_name = "aws_lambda_function.hello-terraform" resource_type = "ZIP_LAMBDA_FUNCTION" original_source_code = "${local.lambda_src_path}" built_output_path = "${local.building_path}/${local.lambda_code_filename}" } depends_on = [ null_resource.build_lambda_function ] } resource "null_resource" "build_lambda_function" { triggers = { build_number = "${timestamp()}" # TODO: calculate hash of lambda function. Mo will have a look at this part } provisioner "local-exec" { command = substr(pathexpand("~"), 0, 1) == "/"? "./py_build.sh \"${local.lambda_src_path}\" \"${local.building_path}\" \"${local.lambda_code_filename}\" Function" : "powershell.exe -File .\\PyBuild.ps1 ${local.lambda_src_path} ${local.building_path} ${local.lambda_code_filename} Function" } } :
ポイントとしてはメタデータリソースとして null_resource を使っています。
サンプルアプリケーションでは local-exec からpy_build.sh
を実行し依存関係の解決などを行っています。
local-exec には以下の記事を参考にしてください。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 src_code=$1 build_path=$2 output_name=$3 resource_type=$4 echo "building ${resource_type} ${src_code} into ${build_path}" temp_path=${build_path}/tmp_building if [[ "${resource_type}" == "Layer" ]]; then temp_path=${build_path}/tmp_building/python echo "new path ${temp_path}" fi pwd mkdir -p ${build_path} rm -rf ${build_path}/* mkdir -p ${build_path}/tmp_building mkdir -p ${temp_path} cp -r $src_code/* ${temp_path} pip install -r ${temp_path}/requirements.txt -t ${temp_path}/. pushd ${build_path}/tmp_building/ && zip -r $output_name . && popd mv "${build_path}/tmp_building/${output_name}" "${build_path}/$output_name" rm -rf ${build_path}/tmp_building
ビルドとローカル実行してみる
では実際に実行してみましょう。
前提として AWS SAM CLI バージョンが 1.63.0 以上である必要があり、Terraform バージョンが 1.1 以上である必要があります。
% sam --version SAM CLI, version 1.64.0 % terraform --version Terraform v1.3.4 on darwin_arm64
ビルド
以下のように--hook-name
でterraform
を指定します。
本日時点で許容されているパラメータはterraform
のみです。
また、プレビュー機能なので、実行すると以下のように確認が発生します。
--beta-features
オプションを追加することで確認を省略することが出来ます。
% sam build --hook-name terraform Supporting Terraform applications is a beta feature. Please confirm if you would like to proceed using AWS SAM CLI with terraform application. You can also enable this beta feature with 'sam build --beta-features'. [y/N]: y Experimental features are enabled for this session. Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/. Running Prepare Hook to prepare the current application Executing prepare hook of hook "terraform" Initializing Terraform application .. Creating terraform plan and getting JSON output ... Generating metadata file Finished generating metadata file. Storing in /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam-iacs/iacs_metadata/template.json Prepare hook completed and metadata file generated at: /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam-iacs/iacs_metadata/template.json Building codeuri: /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/src runtime: python3.8 metadata: {'SkipBuild': False, 'BuildMethod': 'makefile', 'ContextPath': '/Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam-iacs/iacs_metadata', 'WorkingDirectory': '/Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example', 'ProjectRootDirectory': '/Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example'} architecture: x86_64 functions: aws_lambda_function.hello-terraform Running CustomMakeBuilder:CopySource Running CustomMakeBuilder:MakeBuild Current Artifacts Directory : /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam/build/AwsLambdaFunctionHelloTerraform03805755 python3 ".aws-sam-iacs/iacs_metadata/copy_terraform_built_artifacts.py" --expression "|values|root_module|resources|[?address==\"null_resource.sam_metadata_aws_lambda_function_hello_terraform\"]|values|triggers|built_output_path" --directory "/Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam/build/AwsLambdaFunctionHelloTerraform03805755" --target "null_resource.sam_metadata_aws_lambda_function_hello_terraform" Initializing the backend... :
内部でterraform plan
などが実行されています。
なお--hook-name
オプションを省略した場合はterraform
が動作しないので通常どおり SAM テンプレートが要求されます。
% sam build Error: Template file not found at /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/template.yml
ローカル実行
では実行してみます。
ターゲットの関数はリクエストボディの内容を取得して出力するコードがあるので、パラメータを付与して実行してみます。サンプルイベント(sample_event.json
)が用意されていますのでそちらを使いましょう。
% sam local invoke --hook-name terraform --beta-features -e events/sample_event.json Experimental features are enabled for this session. Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/. Skipped prepare hook. Current application is already prepared. Invoking index.lambda_handler (python3.8) Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.8:rapid-1.64.0-x86_64. Mounting /Users/iwasa.takahito/work/hoge1116sam/aws-sam-terraform-examples/zip_based_lambda_functions/lambda-example/.aws-sam/build/AwsLambdaFunctionHelloTerraform03805755 as /var/task:ro,delegated inside runtime container START RequestId: 3a619826-14d5-4a7d-98a9-bd3ac8df6fa0 Version: $LATEST {'Hello': 'World'} END RequestId: 3a619826-14d5-4a7d-98a9-bd3ac8df6fa0 REPORT RequestId: 3a619826-14d5-4a7d-98a9-bd3ac8df6fa0 Init Duration: 2.22 ms Duration: 655.38 ms Billed Duration: 656 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode": 200, "body": "Request Received!", "headers": {"Content-Type": "application/json", "Access-Control-Allow-Origin": "*"}}
sam local invoke
で実行することが出来ました。
割愛しましたが、sam local start-lambda
で同じように実行し、エンドポイントに対して HTTP クライアントから呼び出しすることも出来ます。
さいごに
本日は AWS SAM CLI で Terraform で定義されたテンプレートと Lambda 関数のビルドとローカル実行がプレビュー機能としてサポートされたので実際に試してみました。
まず、サポートされた範囲としてはローカルでのビルドと実行になるので、Terraform でサーバーレスアプリケーションを作成する際のローカル実行補助ツールとして AWS SAM CLI を利用することが出来るようになりました。
Lambda 関数のローカル実行はしたかったが SAM では無く Terraform を使っていてそれが出来なかったというケースで活用出来そうです。